Ext.ns('Ext.ux');

Ext.ux.ComboBoxTree = Ext.extend(Ext.form.ComboBox, {
	dataUrl: null,
	nodePathUrl: null,
	loader: null,
	root: {},
	rootVisible: false,
	rootSelectable: false,
	folderSelectable: true,
	leafSelectable: true,
	showNodePath: false,
	rootValue: undefined,
	store: new Ext.data.SimpleStore({
		fields: [],
		data: [[]]
	}),
	mode: 'local',
	triggerAction: 'all',
	editable: false,
	forceSelection: true,
	tree: null,
	preventCollapse: false,
	
	initComponent: function() {
		this.treeId = Ext.id();
		this.height = this.height || 200;
		this.tpl = '<tpl for=".">'
			     + '<div id="' + this.treeId + '" style="height:' + this.height + 'px"></div>'
			     + '</tpl>';
		Ext.ux.ComboBoxTree.superclass.initComponent.call(this);
	},
	
	setValue: function(value) {
		if (Ext.isObject(value)) {
			this.doSetValue(value);
		} else {
			if (!this.tree) {
				this.initTree();
			}
			
			if (value === this.tree.root.id || Ext.isDefined(this.rootValue) && value === this.rootValue) {
				this.tree.root.select();
				this.doSetValue(this.root);
				return;
			}
			
			var url = this.nodePathUrl;
			if (!url) {
				this.doSetValue({id: value});
				return;
			}
			Ext.Ajax.request({
				url: url,
				async: false,
				scope: this,
				success: function(response, options) {
					var comboTree = this;
					var path = response.responseText;
					path = (path.indexOf('/' == 0 ? '' : '/')) + comboTree.tree.root.id + '/' + path;
					this.tree.selectPath(path, 'id', function(success, node) {
						comboTree.doSetValue(success ? node : null);
					});
				},
				failure: function() {
					alert("failure...");
				}
			});
		}
	},
	doSetValue: function(value) {
		var id = value ? value.id : '';
		var text = value ? value.text : '';
		if (value && (value.loader || value.attributes)) {
			var isRootNode = (value.id == this.tree.root.id);
			if (isRootNode && Ext.isDefined(this.rootValue)) {
				id = this.rootValue;
			}
			if (this.showNodePath) {
				text = isRootNode ? '/' : value.getPath('text').replace('/' + this.tree.root.text, '');
			}
		}
		this.value = id;
		if (this.hiddenField) {
			this.hiddenField.value = id;
		}
		this.lastSelectionText = text;
		this.el.dom.value = text;
		this.fireEvent('select', this, value);
	},
	getValue: function() {
		return Ext.isDefined(this.value) ? this.value : '';
	},
	getValueNode: function() {
		return this.tree ? this.tree.getSelectionModel().getSelectedNode() : null;
	},
	getText: function() {
		return this.lastSelectionText || '';
	},
	reload: function() {
		if (!this.tree) {
			return;
		}
		var node = this.tree.getSelectionModel().getSelectedNode();
		var path = node ? node.getPath() : null;
		this.tree.getLoader().load(this.tree.root, function() {
			if (path) {
				this.tree.selectPath(path);
			}
		}, this);
		this.preventCollapse = true;
	},
	collapse: function() {
		if (this.preventCollapse) {
			this.preventCollapse = false;
			return;
		}
		Ext.ux.ComboBoxTree.superclass.collapse.call(this);
	},
	expend: function() {
		Ext.ux.ComboBoxTree.superclass.expend.call(this);
		if (!this.tree) {
			this.initTree();
		}
	},
	destroy: function() {
		if (this.tree && this.tree.rendered) {
			this.tree.destroy();
		}
		Ext.ux.ComboBoxTree.superclass.destroy.call(this);
	},
	initTree: function() {
		if (!this.list) {
			this.initList();
		}
		var comboTree = this;
		var enableCollapse = function() {
			comboTree.preventCollapse = false;
		};
		var disableCollapse = function() {
			comboTree.preventCollapse = true;
		};
		this.tree = new Ext.tree.TreePanel({
			renderTo: this.treeId,
			autoScroll: true,
			height: this.height,
			animate: true,
			enableDD: false,
			containerScroll: true,
			border: false,
			dataUrl: this.dataUrl,
			loader: this.loader,
			root: this.root,
			rootVisible: this.rootVisible,
			listeners: {
				click: function(node, e) {
					disableCollapse();
					if (node == this.tree.root) {
						if (!this.rootSelectable) {
							return;
						}
					} else if (!node.isLeaf()) {
						if (!this.folderSelectable) {
							return;
						}
					} else {
						if (!this.leafSelectable) {
							return;
						}
					}
					node.select();
					this.setValue(node);
					enableCollapse();
				},
				beforeexpandnode: disableCollapse,
				beforecollapsenode: disableCollapse,
				beforeload: disableCollapse,
				load: enableCollapse,
				expandnode: enableCollapse,
				scope: this
			}
		});
	}
});

Ext.reg('combotree', Ext.ux.ComboBoxTree);